<?php
/**
 * Created by PhpStorm.
 * User: My
 * Date: 2018/12/19
 * Time: 22:13
 */

namespace App\Services;

use App\Exceptions\UserException;
use App\Http\Helper\BusinessHelper;
use App\Http\Helper\Constant;
use TestingPartService;
use TestingQuestionService;

class DimensionAlgoHelper
{
    //需要参与计分的id
    protected $calcQuestionIds = [];
    //需要参与计分的id
    protected $specialQuestionIds = [];
    //所有的题目信息
    protected $question = [];
    //排序的题目信息
    protected $sortQuestion = [];

    //其他标识使用的题目
    protected $mark = [];
    //使用了标识的题目id
    protected $markQuestionIds = [];

    //用户的答案
    protected $answerStr;
    //格式化之后的答案
    protected $answer = [];
    //需要参与计算的答案
    protected $needCalcAnswer = [];

    //分值对应的配置
    protected $scoreConfig = [];

    //最终分值信息
    protected $finalScore;
    //获取配置对应配置信息的key
    protected $finalKey;

    /**
     * DimensionAlgoHelper constructor.
     * @param $tid
     * @throws UserException
     */
    public function __construct($tid) {
        $this->scoreConfig = BusinessHelper::getDimensionScoreConfig();
        //初始化测评的信息
        $this->init($tid);
    }

    /**
     * 计算测评的结果
     * @param $answerStr
     * @return array
     */
    public function calculate($answerStr) {
        $this->dimensionConvertAnswer($answerStr);
        $this->calcBMI();
        $this->calcFinalScore();
        return [
            'score' => $this->finalScore,
            'conclusion' => formatArrValue($this->scoreConfig, $this->finalKey, '')
        ];
    }

    /**
     * 解析最终答案字符串
     * @param $finalAnswer
     * @return array
     */
    public function convertFinalAnswer($finalAnswer) {
        return $this->dimensionConvertFinalAnswer($finalAnswer);
    }

    /**
     * 获取答题数组信息
     * @return array
     */
    public function getAnswer() {
        return $this->answer;
    }

    /**
     * 获取答题结果，转换为字符
     * @return string
     */
    public function getAnswerStr() {
        return $this->arrToFinalAnswer();
    }

    /**
     * 获取标识过的信息
     */
    public function getMarkInfo() {
        return $this->mark;
    }

    /**
     * 获取所有题目信息
     * @return array
     */
    public function getQuestion() {
        return $this->sortQuestion;
    }

    /**
     * 初始化测评的信息
     * @param $tid
     * @throws UserException
     */
    protected function init($tid) {
        $list = TestingPartService::getListByTid($tid);
        if (!$list) {
            throw new UserException("测评ID：{$tid} 不存在维度信息");
        }
        $questionIds = [];
        foreach ($list as $dimensionInfo) {
            $itemIds = json_decode($dimensionInfo['testing_item_ids'], true);
            $questionIds = array_merge($questionIds, $itemIds);
        }

        //获取区分的题目
        $this->getQuestionList($questionIds);
    }

    /**
     * 获取所有的题目列表
     * 区分题目类型
     * @param $questionIds
     */
    protected function getQuestionList($questionIds) {
        $list = TestingQuestionService::getListByIdsOrderByParam($questionIds);
        foreach ($list as $question) {
            //题目按照属性分配开
            if ($question['property'] == Constant::QUESTION_PROPERTY_SCORING) {
                //需要参与计分的id
                array_push($this->calcQuestionIds, $question['id']);
            } elseif ($question['property'] == Constant::QUESTION_PROPERTY_SPECIAL) {
                //需要参与计分的
                array_push($this->calcQuestionIds, $question['id']);
                //特殊项的ID
                array_push($this->specialQuestionIds, $question['id']);
            }

            $this->question[$question['id']] = $question;
            $this->sortQuestion[] = $question;

            //题目的标识
            if ($question['mark']) {
                $this->mark[$question['mark']] = $question;
                array_push($this->markQuestionIds, $question['id']);
            }
        }
    }

    /**
     * 计算bmi的值
     */
    protected function calcBMI() {
        if (isset($this->mark['weight']) && isset($this->mark['height'])) {
            $weight = formatArrValue($this->mark['weight'], 'answer');
            $height = formatArrValue($this->mark['height'], 'answer');
            $bmi = 10000 * $weight / $height / $height;
            if ($bmi > 28) {
                $obj['weight'] = 'A';
                $obj['value'] = 1;
            } elseif ($bmi > 22 && $bmi <=28) {
                $obj['weight'] = 'B';
                $obj['value'] = 2;
            } elseif ($bmi > 18.5 && $bmi <= 22) {
                $obj['weight'] = 'D';
                $obj['value'] = 4;
            } else {
                $obj['weight'] = 'C';
                $obj['value'] = 3;
            }
            $obj['id'] = 'bmi';
            $obj['answer'] = $bmi;
            array_push($this->answer, $obj);
            array_push($this->needCalcAnswer, $obj);
        }
    }

    /**
     * 计算最终的分值
     */
    protected function calcFinalScore() {
        $scoreArr = [
            '1' => 0,
            '2' => 0,
            '3' => 0,
            '4' => 0,
        ];
        foreach ($this->needCalcAnswer as $value) {
            if (!isset($scoreArr[$value['value']])) {
                continue;
            }
            $scoreArr[$value['value']] += 1;
        }
        $total = array_sum($scoreArr);

        if ($total != 0) {
            //得分的比例
            $scoreRatio = [];
            foreach ($scoreArr as $key => $value) {
                $scoreRatio[$key] = $value / $total;
            }
            $this->finalKey = $scoreRatio['1'] >= 0.5 ? 1 : 0;
            $this->finalKey .= $scoreRatio['2'] >= 0.3 ? 1 : 0;
            $this->finalKey .= $scoreRatio['3'] >= 0.1 ? 1 : 0;
            $this->finalKey .= $scoreRatio['4'] >= 0.1 ? 1 : 0;

            $this->finalScore = $scoreArr['1'] + 2 * $scoreArr['2'] + 3 * $scoreArr['3'] + 4 * $scoreArr['4'];
        }
    }

    /**
     * 转换答题为数组，区分各属性的答案
     * @param $answerStr
     */
    protected function dimensionConvertAnswer($answerStr) {
        $answerArr = explode('##', $answerStr);
        if(count($answerArr) > 0){
            foreach ($answerArr as $answer){
                $singleArr = explode(':', $answer);

                if(count($singleArr) > 0){
                    $obj['id'] = $singleArr[0];
                    $obj['value'] = $singleArr[1];
                    $obj['weight'] = $singleArr[2];
                    $obj['answer'] = $singleArr[3];
                    // 特殊项的写入默认的分值
                    if (in_array($singleArr[0], $this->specialQuestionIds)) {
                        $obj['value'] = $this->question[$singleArr[0]]['default_value'];
                        //计入需要计算分数的答题数组中
                        array_push($this->needCalcAnswer, $obj);
                    } elseif (in_array($singleArr[0], $this->calcQuestionIds)) {
                        //计入需要计算分数的答题数组中
                        array_push($this->needCalcAnswer, $obj);
                    }
                    //计入所有的答题数组中
                    array_push($this->answer, $obj);

                    //判断是否标识项
                    if (in_array($singleArr[0], $this->markQuestionIds)) {
                        $this->mark[$this->question[$singleArr[0]]['mark']] = $obj;
                    } elseif ($singleArr[0] == 'bmi') {
                        $this->mark[$singleArr[0]] = $obj;
                    }
                }
            }
        }
    }

    /**
     * 转换最终答题答案为数组，区分各属性的答案
     * @param $finalAnswerStr
     * @return array
     */
    protected function dimensionConvertFinalAnswer($finalAnswerStr) {
        $resultAnswer = [];
        $answerArr = explode('##', $finalAnswerStr);
        if(count($answerArr) > 0){
            foreach ($answerArr as $answer){
                $singleArr = explode(':', $answer);

                if(count($singleArr) > 0){
                    $obj['id'] = $singleArr[0];
                    $obj['value'] = $singleArr[1];
                    $obj['weight'] = $singleArr[2];
                    $obj['answer'] = $singleArr[3];
                    // 特殊项的写入默认的分值
                    if (in_array($singleArr[0], $this->specialQuestionIds)) {
                        $obj['value'] = $this->question[$singleArr[0]]['default_value'];
                        //计入需要计算分数的答题数组中
                        array_push($this->needCalcAnswer, $obj);
                    } elseif (in_array($singleArr[0], $this->calcQuestionIds)) {
                        //计入需要计算分数的答题数组中
                        array_push($this->needCalcAnswer, $obj);
                    }
                    //计入所有的答题数组中
                    array_push($this->answer, $obj);
                    $resultAnswer[$singleArr[0]] = $obj;

                    //判断是否标识项
                    if (in_array($singleArr[0], $this->markQuestionIds)) {
                        $this->mark[$this->question[$singleArr[0]]['mark']] = $obj;
                    } elseif ($singleArr[0] == 'bmi') {
                        $this->mark[$singleArr[0]] = $obj;
                    }
                }
            }
        }
        return $resultAnswer;
    }

    /**
     * 转换为最终答案
     * @return string
     */
    protected function arrToFinalAnswer() {
        $arr = [];
        $answers = [];
        foreach($this->answer as $k => $v){
            $arr[0] = $v['id'];
            $arr[1] = $v['value'];
            $arr[2] = $v['weight'];
            $arr[3] = $v['answer'];
            $str = implode(":", $arr);
            $answers[$k] = $str;
        }
        $answerStr = implode("##", $answers);
        return $answerStr;
    }
}